#include "Bsp_adc.h"

#include "Bsp_dac.h"
#include "debug.h"

#include <string.h>

static uint8_t Cur_Ctl_pin              = 0; // 用于记录当前选中的ADC通道
Res_adj_data_t res_data_arr[ADC_CH_MAX] = { 0 };
float          TEMP_Value;
#if (defined(HARD_VERSION_V1) || defined(HARD_VERSION_V2))
#define ADC_CTL_PIN_MODE FL_GPIO_MODE_OUTPUT
#elif defined(HARD_VERSION_V2_1)
#define ADC_CTL_PIN_MODE FL_GPIO_MODE_INPUT
#endif
// clang-format off
//ADC_Ctl_ init :ctl_pin  adj、read_pin
USR_GPIO_Init adc_ctl_pin[]={
//           PORT  pin             mode                outputType               pull       remapPin   analogSwitch 
//Ctrl_pin
[PULS_01] = {GPIOA,{FL_GPIO_PIN_14 ,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
[PULS_02] = {GPIOA,{FL_GPIO_PIN_8 ,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
[PULS_03] = {GPIOA,{FL_GPIO_PIN_9 ,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
[PULS_04] = {GPIOB,{FL_GPIO_PIN_1 ,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
[PULS_05] = {GPIOB,{FL_GPIO_PIN_4 ,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
[PULS_06] = {GPIOB,{FL_GPIO_PIN_5 ,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
[PULS_07] = {GPIOB,{FL_GPIO_PIN_7 ,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
[PULS_08] = {GPIOB,{FL_GPIO_PIN_10,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
[PULS_09] = {GPIOB,{FL_GPIO_PIN_11,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
[PULS_10] = {GPIOC,{FL_GPIO_PIN_5 ,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
[PULS_11] = {GPIOC,{FL_GPIO_PIN_7 ,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
[PULS_12] = {GPIOC,{FL_GPIO_PIN_8 ,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
#if 1
[PULS_13] = {GPIOC,{FL_GPIO_PIN_9 ,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
[PULS_14] = {GPIOC,{FL_GPIO_PIN_10,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
#endif

// [NTC_EN ] = {GPIOC,{FL_GPIO_PIN_9 ,ADC_CTL_PIN_MODE ,FL_GPIO_OUTPUT_OPENDRAIN,FL_DISABLE,FL_DISABLE,FL_DISABLE}},
// other
[ADC_IN]  = {GPIOA,{FL_GPIO_PIN_13,FL_GPIO_MODE_ANALOG,FL_GPIO_OUTPUT_PUSHPULL,FL_DISABLE,FL_DISABLE,FL_DISABLE}},//ADC_IN4
};
// clang-format on

static void  InitMovingAvgFilter(MovingAvgFilter_t *filter);
static float UpdateMovingAvgFilter(MovingAvgFilter_t *filter, float newValue);

void Bsp_ADC_init(void)
{

    FL_ADC_CommonInitTypeDef Common_InitStruct;
    FL_ADC_InitTypeDef       ADC_InitStruct;
    FL_NVIC_ConfigTypeDef    InterruptConfigStruct;
    int                      i = 0;

    // 控制引脚初始化
    for (i = 0; i < (sizeof(adc_ctl_pin) / sizeof(adc_ctl_pin[0])); i++) {
        FL_GPIO_Init(adc_ctl_pin[i].GPIOx, &adc_ctl_pin[i].init_type);
        FL_GPIO_SetOutputPin(adc_ctl_pin[i].GPIOx, adc_ctl_pin[i].init_type.pin);
    }

    // 初始化所有通道的滤波器
    for (i = 0; i < ADC_CH_MAX; i++) {
        InitMovingAvgFilter(&res_data_arr[i].filter);
    }

    // ADC Common init
    Common_InitStruct.clockSource    = FL_CMU_ADC_CLK_SOURCE_PLL;
    Common_InitStruct.clockPrescaler = FL_ADC_CLK_PSC_DIV32;
#if (defined(HARD_VERSION_V1) || defined(HARD_VERSION_V2))
    Common_InitStruct.referenceSource = FL_ADC_REF_SOURCE_VREFP;
#elif defined(HARD_VERSION_V2_1)
    Common_InitStruct.referenceSource = FL_ADC_REF_SOURCE_VDDA;
    // Common_InitStruct.referenceSource = FL_ADC_REF_SOURCE_VREFP;
#endif
    Common_InitStruct.bitWidth = FL_ADC_BIT_WIDTH_12B;
    FL_ADC_CommonInit(&Common_InitStruct);

    // ADC init
    ADC_InitStruct.conversionMode        = FL_ADC_CONV_MODE_SINGLE;
    ADC_InitStruct.autoMode              = FL_ADC_SINGLE_CONV_MODE_AUTO;
    ADC_InitStruct.waitMode              = FL_DISABLE;
    ADC_InitStruct.overrunMode           = FL_ENABLE;
    ADC_InitStruct.scanDirection         = FL_ADC_SEQ_SCAN_DIR_FORWARD;
    ADC_InitStruct.externalTrigConv      = FL_ADC_TRIGGER_EDGE_NONE;
    // ADC_InitStruct.triggerSource = FL_ADC_TRGI_BSTIM16;
    ADC_InitStruct.triggerSource         = FL_DISABLE;
    ADC_InitStruct.fastChannelTime       = FL_ADC_FAST_CH_SAMPLING_TIME_32_ADCCLK;
    ADC_InitStruct.lowChannelTime        = FL_ADC_SLOW_CH_SAMPLING_TIME_512_ADCCLK;
    ADC_InitStruct.oversamplingMode      = FL_ENABLE;
    ADC_InitStruct.overSampingMultiplier = FL_ADC_OVERSAMPLING_MUL_16X;
    ADC_InitStruct.oversamplingShift     = FL_ADC_OVERSAMPLING_SHIFT_4B;
    FL_ADC_Init(ADC, &ADC_InitStruct);
    FL_ADC_EnableSequencerChannel(ADC, FL_ADC_EXTERNAL_CH4);

    FL_ADC_ClearFlag_EndOfConversion(ADC);       /*清标志*/
    FL_ADC_EnableIT_EndOfConversion(ADC);

    InterruptConfigStruct.preemptPriority = 0x2; /*配置中断优先级*/
    FL_NVIC_Init(&InterruptConfigStruct, ADC_IRQn);

    //////////////////////////
    // start
    i = PULS_01;
    FL_GPIO_SetOutputPin(adc_ctl_pin[i].GPIOx, adc_ctl_pin[i].init_type.pin);

    ADC_switch_ch(1);
    // 定时器
    // ADC
    FL_ADC_Enable(ADC); // 启动ADC

    // FL_ADC_EnableSWConversion(ADC);
    // XXX:开启定时器，定时中断开启ADC转换
    FL_BSTIM16_Enable(BSTIM16);
}

// XXX:考虑做触发转换，而不是中断调用
void BSTIM_IRQHandler(void)
{
    if (FL_BSTIM16_IsEnabledIT_Update(BSTIM16) && FL_BSTIM16_IsActiveFlag_Update(BSTIM16)) {
        FL_BSTIM16_ClearFlag_Update(BSTIM16);

        FL_ADC_EnableSWConversion(ADC);       // 使能ADC软件触发转换
        FL_ADC_EnableIT_EndOfConversion(ADC); // 使能ADC转换完成中断

        FL_BSTIM16_WriteCounter(BSTIM16, 0);
        FL_BSTIM16_Disable(BSTIM16);
    }
}

uint16_t volatile Xadc;
float Cur_Res;
/**
 * @brief  选择当前adc选中的阻值通道
 * @note
 * @param
 * @param out: Cur_Ctl_pin 当前选中的pin通道
 * @retval None
 */
void  ADC_switch_ch(uint8_t first_flag)
{
    int i = 0;
    if (!first_flag) {
        Cur_Ctl_pin++;
        if (Cur_Ctl_pin >= ADC_CH_MAX) {
            Cur_Ctl_pin = PULS_01; // 回到第一个通道
            // 取消温度通道
            // FL_VREF_DisableVREFBuffer(VREF);
            // FL_ADC_DisableSequencerChannel(ADC, FL_ADC_INTERNAL_TS);
        }
        // else if (Cur_Ctl_pin == ADC_CH_MAX - 1) {
        //     // 启动温度传感器相关功能
        //     FL_VREF_EnableVREFBuffer(VREF);
        //     FL_VREF_EnableVPTATBuffer(VREF);
        //     FL_ADC_EnableSequencerChannel(ADC, FL_ADC_INTERNAL_TS);
        // }
    }
    else {
        Cur_Ctl_pin = 0; // 首次初始化从0开始
    }
    // Cur_Ctl_pin = PULS_07;
    // Cur_Ctl_pin = NTC_EN;
    // TODO:临时调试

#if (defined(HARD_VERSION_V1) || defined(HARD_VERSION_V2))
    for (i = 0; i < ADC_CH_MAX; i++) {
        FL_GPIO_SetOutputPin(adc_ctl_pin[i].GPIOx, adc_ctl_pin[i].init_type.pin);
    }
    // 拉低pin可导通
    FL_GPIO_ResetOutputPin(adc_ctl_pin[Cur_Ctl_pin].GPIOx, adc_ctl_pin[Cur_Ctl_pin].init_type.pin);

#elif defined(HARD_VERSION_V2_1)
    for (i = 0; i < ADC_CH_MAX; i++) {
        FL_GPIO_Init(adc_ctl_pin[i].GPIOx, &adc_ctl_pin[i].init_type);
    }
    {
        FL_GPIO_InitTypeDef initStruct;
        FL_GPIO_StructInit(&initStruct);

        initStruct.pin        = adc_ctl_pin[Cur_Ctl_pin].init_type.pin;
        initStruct.mode       = FL_GPIO_MODE_OUTPUT;
        initStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;

        FL_GPIO_Init(adc_ctl_pin[Cur_Ctl_pin].GPIOx, &initStruct);
        FL_GPIO_SetOutputPin(adc_ctl_pin[Cur_Ctl_pin].GPIOx, adc_ctl_pin[Cur_Ctl_pin].init_type.pin);
    }
#endif
}

void ADC_IRQHandler(void)
{
    static uint8_t volatile conver_cnt = 0,                // 记录ADC转换次数
        switch_ch_flag                 = 0;                // 用于标记是否需要切换ADC通道
    uint32_t IF_Flag, EosIF_Flag;
    IF_Flag    = FL_ADC_IsActiveFlag_EndOfConversion(ADC); // 获取中断标志状态
    EosIF_Flag = FL_ADC_IsActiveFlag_EndOfSequence(ADC);

    /* ADC转换完成中断 */
    if (0x01U == IF_Flag) {
        FL_ADC_ClearFlag_EndOfConversion(ADC); // 清标志
        Xadc = FL_ADC_ReadConversionData(ADC); // 读取ADC转换结果

        conver_cnt++;
        if (conver_cnt == 1)                   // 第一次转换 - 处理外部阻值测量
        {                                      // ADC外部（阻值测量）通道优先转换
            if (0 != DAC_value_adj(Xadc, &Cur_Res)) {
                // 数据可用，更新至结构体后，开始测量下一组数据
                switch_ch_flag = 1;
                // res_data_arr[Cur_Ctl_pin].Res_value = Cur_Res;

                // /* 检查阻值是否超出范围 */
                // if (res_data_arr[Cur_Ctl_pin].Res_value > RES_VALUE_MAX) {
                //     res_data_arr[Cur_Ctl_pin].Res_value = RES_VALUE_INVALID;
                // }

                /* 检查阻值是否超出范围 */
                if (Cur_Res > RES_VALUE_MAX) {
                    res_data_arr[Cur_Ctl_pin].Res_value = RES_VALUE_INVALID;
                }
                else {
                    // 应用移动平均滤波
                    res_data_arr[Cur_Ctl_pin].Res_value =
                        UpdateMovingAvgFilter(&res_data_arr[Cur_Ctl_pin].filter, Cur_Res);
                }
            }
        }
        else // 第二次转换 - 处理温度测量
        {
            TEMP_Value = ADC2Temp(Xadc);
        }
    }

    /* ADC序列转换完成中断 */
    if (0x01U == EosIF_Flag) {
        FL_ADC_DisableIT_EndOfConversion(ADC);
        FL_ADC_ClearFlag_EndOfSequence(ADC);

        // 允许转换引脚
        if ((switch_ch_flag)) {
            switch_ch_flag = 0;
            ADC_switch_ch(0); // 切换到下一个ADC通道
        }
        // 开启下次转换
        FL_BSTIM16_Enable(BSTIM16); // 启用TIM，延迟待电路稳定后触发ADC转换
        conver_cnt = 0;
    }
}

/**
 * @brief 初始化滤波器
 *
 * @param filter
 */
static void InitMovingAvgFilter(MovingAvgFilter_t *filter)
{
    memset(filter->buffer, 0, sizeof(filter->buffer));
    filter->index = 0;
    filter->count = 0;
    filter->sum   = 0;
}

/**
 * @brief 添加数据到滤波器并获取滤波后的值
 *
 * @param filter
 * @param newValue
 * @return float
 */
static float UpdateMovingAvgFilter(MovingAvgFilter_t *filter, float newValue)
{
    // 如果缓冲区已满，减去将被替换的值
    if (filter->count == FILTER_SIZE) {
        filter->sum -= filter->buffer[filter->index];
    }
    else {
        filter->count++;
    }

    // 添加新值到缓冲区
    filter->buffer[filter->index] = newValue;
    filter->sum += newValue;

    // 更新索引
    filter->index = (filter->index + 1) % FILTER_SIZE;

    // 返回平均值
    return filter->sum / filter->count;
}
